java编码解码加密解密 | 您所在的位置:网站首页 › md5加解密 流程 › java编码解码加密解密 |
md5
md5是一种散列算法,不可逆,是一种消息摘要算法,生成的字节数组的长度是128位,也就是等于16个字节,那么有的字节转化为字符之后,这些字符不一定是存在于ascii码之中,通常为了便于输出,我们会将每个字节转变为16进制字符串,每个16进制都是2个字符,所以md5转化之后的字符是32个字符。 这里有个技术点需要注意的是,在对每个字节进行转化为16进制的字符串的 时候,0-15这几个值的字节,转化为的字符串的长度都是1,所以需要在前面补0 jdk原生md5 /** * jdk原生md5 */ public static void md5() throws Exception { String str = "hello聚合"; String algorithm = "MD5"; MessageDigest instance = MessageDigest.getInstance(algorithm); byte[] digest = instance.digest(str.getBytes(StandardCharsets.UTF_8)); System.out.println(new String(digest)); //如果直接输出的话,是乱码�G�s�.u�Iz�۲� //这是因为md5生成的消息摘要是128位,也就是等于16个字节,那么有的字节转化为字符之后,这些字符不一定是存在于ascii码之中的 //通常为了便于输出,我们会将每个字节转变为16进制字符串,每个16进制都是2个字符,所以md5转化之后的字符是32个字符 StringBuilder stringBuilder = new StringBuilder(); for (byte b : digest) { //每个字节转与0xff(1111 1111)按位与,得到这个字节的补码 String hex = Integer.toHexString(b & 0xff); //如果生成的16进制的字符的长度是1,那么需要在前面补0,比如 //0,5,10,13,15的16进制分别是是0,5,a,d,f,长度只有1,所以需要前面补0 if (hex.length() == 1) { hex = "0" + hex; } stringBuilder.append(hex); } System.out.println(stringBuilder); } } 使用commons-codec需要引入jar包 commons-codec commons-codec 1.15 /** * 使用commons-codec */ public static void md5codec() { String str = "hello聚合"; String encode = DigestUtils.md5Hex(str.getBytes(StandardCharsets.UTF_8)); System.out.println(encode); } 全部代码 package codec.md5; import org.apache.commons.codec.digest.DigestUtils; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; /** * @author micro.cloud.fly * @date 2021/8/30 11:28 上午 * @desc md5消息摘要算法学习笔记 */ public class Demo1 { public static void main(String[] args) throws Exception { md5(); System.out.println(); md5codec(); } /** * jdk原生md5 */ public static void md5() throws Exception { String str = "hello聚合"; String algorithm = "MD5"; MessageDigest instance = MessageDigest.getInstance(algorithm); byte[] digest = instance.digest(str.getBytes(StandardCharsets.UTF_8)); System.out.println(new String(digest)); //如果直接输出的话,是乱码�G�s�.u�Iz�۲� //这是因为md5生成的消息摘要是128位,也就是等于16个字节,那么有的字节转化为字符之后,这些字符不一定是存在于ascii码之中的 //通常为了便于输出,我们会将每个字节转变为16进制字符串,每个16进制都是2个字符,所以md5转化之后的字符是32个字符 StringBuilder stringBuilder = new StringBuilder(); for (byte b : digest) { //每个字节转与0xff(1111 1111)按位与,得到这个字节的补码 String hex = Integer.toHexString(b & 0xff); //如果生成的16进制的字符的长度是1,那么需要在前面补0,比如 //0,5,10,13,15的16进制分别是是0,5,a,d,f,长度只有1,所以需要前面补0 if (hex.length() == 1) { hex = "0" + hex; } stringBuilder.append(hex); } System.out.println(stringBuilder); } /** * 使用commons-codec */ public static void md5codec() { String str = "hello聚合"; String encode = DigestUtils.md5Hex(str.getBytes(StandardCharsets.UTF_8)); System.out.println(encode); } } SHA-256sha-256和md5一样,都是消息摘要算法,只不过是摘要后的长度是256位,也就是32个字节,同理,在转化为16进制的字符串之后,是64个字节,实现了md5之后,只要把算法algorithm改为SHA-256即可,以下是全部的代码 全部代码 package codec.sha256; import org.apache.commons.codec.digest.DigestUtils; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; /** * @author micro.cloud.fly * @date 2021/8/30 11:28 上午 * @desc sha256消息摘要算法学习笔记 */ public class Demo { public static void main(String[] args) throws Exception { md5(); System.out.println(); md5codec(); } /** * jdk原生md5 */ public static void md5() throws Exception { String str = "hello聚合"; String algorithm = "SHA-256"; MessageDigest instance = MessageDigest.getInstance(algorithm); byte[] digest = instance.digest(str.getBytes(StandardCharsets.UTF_8)); System.out.println(new String(digest)); //如果直接输出的话,是乱码�G�s�.u�Iz�۲� //这是因为md5生成的消息摘要是128位,也就是等于16个字节,那么有的字节转化为字符之后,这些字符不一定是存在于ascii码之中的 //通常为了便于输出,我们会将每个字节转变为16进制字符串,每个16进制都是2个字符,所以md5转化之后的字符是32个字符 StringBuilder stringBuilder = new StringBuilder(); for (byte b : digest) { //每个字节转与0xff(1111 1111)按位与,得到这个字节的补码 String hex = Integer.toHexString(b & 0xff); //如果生成的16进制的字符的长度是1,那么需要在前面补0,比如 //0,5,10,13,15的16进制分别是是0,5,a,d,f,长度只有1,所以需要前面补0 if (hex.length() == 1) { hex = "0" + hex; } stringBuilder.append(hex); } System.out.println(stringBuilder); } /** * 使用commons-codec */ public static void md5codec() { String str = "hello聚合"; String encode = DigestUtils.sha256Hex(str.getBytes(StandardCharsets.UTF_8)); System.out.println(encode); } } SHA-512同sha-256原理一样,只要把algorithm算法名改为sha-512即可,以下是全部代码 package codec.sha512; import org.apache.commons.codec.digest.DigestUtils; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; /** * @author micro.cloud.fly * @date 2021/8/30 11:28 上午 * @desc sha512消息摘要算法学习笔记 */ public class Demo { public static void main(String[] args) throws Exception { md5(); System.out.println(); md5codec(); } /** * jdk原生 */ public static void md5() throws Exception { String str = "hello聚合"; String algorithm = "SHA-512"; MessageDigest instance = MessageDigest.getInstance(algorithm); byte[] digest = instance.digest(str.getBytes(StandardCharsets.UTF_8)); System.out.println(new String(digest)); //如果直接输出的话,是乱码�G�s�.u�Iz�۲� //这是因为md5生成的消息摘要是128位,也就是等于16个字节,那么有的字节转化为字符之后,这些字符不一定是存在于ascii码之中的 //通常为了便于输出,我们会将每个字节转变为16进制字符串,每个16进制都是2个字符,所以md5转化之后的字符是32个字符 StringBuilder stringBuilder = new StringBuilder(); for (byte b : digest) { //每个字节转与0xff(1111 1111)按位与,得到这个字节的补码 String hex = Integer.toHexString(b & 0xff); //如果生成的16进制的字符的长度是1,那么需要在前面补0,比如 //0,5,10,13,15的16进制分别是是0,5,a,d,f,长度只有1,所以需要前面补0 if (hex.length() == 1) { hex = "0" + hex; } stringBuilder.append(hex); } System.out.println(stringBuilder); } /** * 使用commons-codec */ public static void md5codec() { String str = "hello聚合"; String encode = DigestUtils.sha512Hex(str.getBytes(StandardCharsets.UTF_8)); System.out.println(encode); } } MACmac也是一种消息摘要,同md5、SHA256算法不同的是,它在进行消息摘要的时候,需要一个key,相同于密钥,mac算法有macMD5、macSHA256、macSHA512等多种,在实现的时候,也是只需要改一个算法名称即可,以下是实现的全部代码 package codec.lesson05_mac; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.HmacAlgorithms; import org.apache.commons.codec.digest.HmacUtils; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; /** * @author micro.cloud.fly * @date 2021/8/30 11:28 上午 * @desc mac消息摘要算法学习笔记 */ public class Demo1 { public static void main(String[] args) throws Exception { mac(); System.out.println(); maccodec(); } /** * jdk原生md5 */ public static void mac() throws Exception { String str = "hello聚合"; String key = "123"; String algorithm = "HmacMD5"; //使用其他算法,只需要改一下名字即可 algorithm = "HmacSHA256"; algorithm = "HmacSHA512"; //实例化mac对象 Mac mac = Mac.getInstance(algorithm); //实例化key对象 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm); //mac对象初始化 mac.init(secretKeySpec); byte[] bytes = mac.doFinal(str.getBytes(StandardCharsets.UTF_8)); StringBuilder stringBuilder = new StringBuilder(); for (byte b : bytes) { //每个字节转与0xff(1111 1111)按位与,得到这个字节的补码 String hex = Integer.toHexString(b & 0xff); //如果生成的16进制的字符的长度是1,那么需要在前面补0,比如 //0,5,10,13,15的16进制分别是是0,5,a,d,f,长度只有1,所以需要前面补0 if (hex.length() == 1) { hex = "0" + hex; } stringBuilder.append(hex); } System.out.println(stringBuilder); } /** * 使用commons-codec */ public static void maccodec() { String str = "hello聚合"; String key = "123"; System.out.println("hmacMD5:"+new HmacUtils(HmacAlgorithms.HMAC_MD5, key.getBytes(StandardCharsets.UTF_8)).hmacHex(str.getBytes(StandardCharsets.UTF_8))); System.out.println("hmacSHA256:"+new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key.getBytes(StandardCharsets.UTF_8)).hmacHex(str.getBytes(StandardCharsets.UTF_8))); System.out.println("hmacSHA512:"+new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key.getBytes(StandardCharsets.UTF_8)).hmacHex(str.getBytes(StandardCharsets.UTF_8))); } } DESdes是一种对称加密算法,相对于非对称加密算法来说,更快,现在des已经过时,被AES给取代了,需要注意的是,des算法的时候,key必须是8个字节,不然会报错。以下是使用des加密解密的全部代码。 package codec; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; /** * @author micro.cloud.fly * @date 2021/8/30 2:04 下午 * @desc 学习des算法,des是对称加密,比起非对称加密,有点是更快,因为只使用一个key */ public class lesson06_DES { public static void main(String[] args) throws Exception { String encryptedString = encrypt(); String decryptedString = decrypt(encryptedString); System.out.println(decryptedString); } private static String decrypt(String encryptedString) throws Exception { String algorithm = "DES"; Cipher cipher = Cipher.getInstance(algorithm); String key = "12345678";//这里必须是8个字节 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); //传参过来的明文,是base64编码后的内容,所以,需要先进行base64解码 byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(encryptedString.getBytes(StandardCharsets.UTF_8))); return new String(bytes, StandardCharsets.UTF_8); } /** * 使用DES加密 * * @return 加密后的内容 */ public static String encrypt() throws Exception { String algorithm = "DES"; String str = "hello聚合"; //cipher是密码的意思,这里是实例化一个cipher对象, //这里ECB是指加密的模式,是java的默认加密模式,PKCS7Padding是指填充模式,加密模式和填充模式也可以不进行指定 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); String key = "12345678";//这里必须是8个字节 //实例化一个密钥,第一个参数是密钥,第二个参数是算法 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm); //cipher初始化,第一个参数是加解密模式,即,cipher是为了加密,还是用来解密,第二个参数是密钥对象 cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)); //得到的是字节数组,通常的做法是把此处的字节数组转为base64进行展示 byte[] encode = Base64.getEncoder().encode(bytes); System.out.println(new String(encode, StandardCharsets.UTF_8)); return new String(encode); } } AESaes和des差不多,只需要改algorithm的名字即可,不同点是,aes的key的长度必须是16、24、32个字节,不过可以通过key generator进行优化,优化后可以使用任意的长度的key,当使用填充模式为NoPadding的方式时,des的key必须为8个字节,aes的key必须是16,24,32个字节。 ECB:java默认的 加密模式,是指把明文分组之后,每个组进行并行加密,然后拼接,所以效率会比较高 CBC:采用的是将明文进行分组,后面分组的内容加密时,依赖前一个分组加密后的密文,也就是每次加密后的密文,后面的组进行加密的时候,都根据这个密文与后面的组的明文进行一起加密,这种模式下,需要一个initialization vector,简称IV,即初始化向量,这个初始化向量默认必须是16个字节。 以下是完整的代码展示 package codec.lesson07_AES; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Base64; /** * @author micro.cloud.fly * @date 2021/8/30 2:04 下午 * @desc 学习aes算法,aes是对称加密,比起非对称加密,有点是更快,因为只使用一个key */ public class Demo02 { public static void main(String[] args) throws Exception { //常规加密 String encryptedString = encrypt(); //常规解密 String decryptedString = decrypt(encryptedString); System.out.println(decryptedString); System.out.println(); //优化后的加密 String s = encryptOptimise(); //优化后的解密 String s1 = decryptOptimise(s); System.out.println(s1); } /** * 使用AES加密 * * @return 加密后的内容 */ public static String encrypt() throws Exception { String algorithm = "AES"; String str = "hello聚合"; //cipher是密码的意思,这里是实例化一个cipher对象, //这里ECB是指加密的模式,是java的默认加密模式, // PKCS5Padding是指填充模式,也是java默认的填充方式, Cipher cipher = Cipher.getInstance(algorithm); //这里与des区别的地方是,des必须是8个字节,而aes必须是16,24,32个字节 /*在接口AESConstants中明确规定了长度 interface AESConstants { int AES_BLOCK_SIZE = 16; int[] AES_KEYSIZES = new int[]{16, 24, 32}; }*/ String key = "1234567812345678"; //实例化一个密钥,第一个参数是密钥,第二个参数是算法 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm); //cipher初始化,第一个参数是加解密模式,即,cipher是为了加密,还是用来解密,第二个参数是密钥对象 //默认的是ECB加密模式,如果使用的CBC模式的话,需要多传一个IV向量,即initialization vector String iv = "12345678abcdabcd"; IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); //CBC模式下,必须有第三个参数IV //cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivParameterSpec); byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)); //得到的是字节数组,通常的做法是把此处的字节数组转为base64进行展示 byte[] encode = Base64.getEncoder().encode(bytes); System.out.println(new String(encode, StandardCharsets.UTF_8)); return new String(encode); } private static String decrypt(String encryptedString) throws Exception { String algorithm = "AES"; Cipher cipher = Cipher.getInstance(algorithm); String key = "1234567812345678";//这里必须是8个字节 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); //传参过来的明文,是base64编码后的内容,所以,需要先进行base64解码 byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(encryptedString.getBytes(StandardCharsets.UTF_8))); return new String(bytes, StandardCharsets.UTF_8); } /** * 优化后的aes加密算法,这是因为默认key的长度只能是16, 24, 32个字节,此处使用key工厂,可以传递任意字节的密钥 * * @return 加密后的内容 */ public static String encryptOptimise() throws Exception { String algorithm = "AES"; String str = "hello聚合"; //cipher是密码的意思,这里是实例化一个cipher对象, Cipher cipher = Cipher.getInstance(algorithm); //实例化key工厂 KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm); //初始化secureRandom,并指定生成key的算法 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); String key = "1234567812345"; //设置key工厂的种子 secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8)); //第一个参数是生成原始key的长度,第二个参数是SecureRandom对象 keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); //获取到新的密钥的字节数组 byte[] encodedKey = secretKey.getEncoded(); //实例化一个密钥,第一个参数是密钥,第二个参数是算法 SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, algorithm); //cipher初始化,第一个参数是加解密模式,即,cipher是为了加密,还是用来解密,第二个参数是密钥对象 cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)); //得到的是字节数组,通常的做法是把此处的字节数组转为base64进行展示 byte[] encode = Base64.getEncoder().encode(bytes); System.out.println(new String(encode, StandardCharsets.UTF_8)); return new String(encode); } /** * 优化后的aes解密算法,这是因为默认key的长度只能是16, 24, 32个字节,此处使用key工厂,可以传递任意字节的密钥 * * @return 加密后的内容 */ public static String decryptOptimise(String encryptStr) throws Exception { String algorithm = "AES"; //cipher是密码的意思,这里是实例化一个cipher对象, Cipher cipher = Cipher.getInstance(algorithm); //实例化key工厂 KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm); //初始化secureRandom,并指定生成key的算法 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); String key = "1234567812345"; //设置key工厂的种子 secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8)); //第一个参数是生成原始key的长度,第二个参数是SecureRandom对象 keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); //获取到新的密钥的字节数组 byte[] encodedKey = secretKey.getEncoded(); //实例化一个密钥,第一个参数是密钥,第二个参数是算法 SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, algorithm); //cipher初始化,第一个参数是加解密模式,即,cipher是为了加密,还是用来解密,第二个参数是密钥对象 cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(encryptStr.getBytes(StandardCharsets.UTF_8))); return new String(bytes); } } RSA 非对称加密算法 简介:① 非对称加密算法又称现代加密算法。 ② 非对称加密是计算机通信安全的基石,保证了加密数据不会被破解。 ③ 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey) 和私有密(privatekey) ④ 公开密钥和私有密钥是一对 ⑤ 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。 ⑥ 如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密。 ⑦ 因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 原理示例首先生成密钥对, 公钥为(5,14), 私钥为(11,14) 现在A希望将原文2发送给B A使用公钥加密数据. 2的5次方mod 14 = 4 , 将密文4发送给B B使用私钥解密数据. 4的11次方mod14 = 2, 得到原文2 特点 加密和解密使用不同的密钥 如果使用私钥加密, 只能使用公钥解密 如果使用公钥加密, 只能使用私钥解密 处理数据的速度较慢, 因为安全级别高 常见算法 RSAECC 数字签名 |
CopyRight 2018-2019 实验室设备网 版权所有 |